#include "ScriptPCH.h"
#include "World.h"
#include "DatabaseEnv.h"
#include "custom_defines.h"
#include <cstring>

//This function is called when the player logs in (every login)
void OnLogin(Player *pPlayer)
{
    uint32 BubbleCD = pPlayer->GetSpellCooldownDelay(642);
    ChatHandler(pPlayer).PSendSysMessage("%s",pPlayer->GetSpellCooldownDelay(642));
    pPlayer->CastSpell(pPlayer,642,true);
    pPlayer->RemoveSpellCooldown(642,true);
    pPlayer->AddSpellCooldown(642,NULL,BubbleCD);
    pPlayer->RemoveAura(25771,AURA_REMOVE_BY_DEFAULT);
}

bool DoPvPChecks(Player *attacker,Player *victim)
{
    if (attacker->isGameMaster() == true || victim->isGameMaster() == true)
    {
        victim->KillStreak = 0;
        victim->TotalDeaths++;
    }
    else
    {
        victim->KillStreak = 0;
        victim->TotalDeaths++;
        if (attacker == victim)
        {
            ChatHandler(attacker).PSendSysMessage("%s[PvP System]%s Suicide!",MSG_COLOR_MAGENTA,MSG_COLOR_WHITE);
            attacker->TotalDeaths++;
            return false;
        }

        if (victim->HasAura(2479,0) || victim->HasAura(2479,1))
        {
            ChatHandler(attacker).PSendSysMessage("%s[PvP System]%s Hes not worth money or honor yet!",MSG_COLOR_MAGENTA,MSG_COLOR_WHITE);
            return false;
        }

        if (attacker->GetSession()->GetRemoteAddress() == victim->GetSession()->GetRemoteAddress())
        {
            ChatHandler(attacker).PSendSysMessage("%s[Anti Farming System]%s You have same ip as your victim", MSG_COLOR_MAGENTA, MSG_COLOR_WHITE);
            ChatHandler(attacker).PSendSysMessage("%sthis means you are on same network and could farm money together.", MSG_COLOR_WHITE);
            return false;
        }

        if (victim->GetGUID() == attacker->ALastGuid)
        {
            attacker->ALastGuidCount++;
            if (attacker->ALastGuidCount >= 3 && attacker->ALastGuidCount <= 5)
            {
                ChatHandler(attacker).PSendSysMessage("%s[Anti Farming System]%s You don't get awarded for killing a player more than 3 times in a row!.", MSG_COLOR_MAGENTA, MSG_COLOR_WHITE);
                return false;
            }
            else if (attacker->ALastGuidCount > 5 && attacker->ALastGuidCount < 10)
            {
                ChatHandler(attacker).PSendSysMessage("%s[Anti Farming System]%s You have killed this guy %u times in a row now whats your problem?", MSG_COLOR_MAGENTA, MSG_COLOR_WHITE, attacker->ALastGuidCount);
                return false;
            }
            else if (attacker->ALastGuidCount >= 10)
            {
                ChatHandler(attacker).PSendSysMessage("%s[Anti Farming System]%s We don't like gankers GTFO!", MSG_COLOR_MAGENTA, MSG_COLOR_WHITE);
                attacker->AddAura(15007, attacker);
                attacker->GetSession()->KickPlayer();
                return false;
            }
        }
        else if (attacker->GetGUID() == victim->VLastGuid)
        {
            victim->VLastGuidCount++;
            if (victim->VLastGuidCount >= 3 && victim->VLastGuidCount <= 5)
            {
                ChatHandler(attacker).PSendSysMessage("%s[Anti Farming System]%s You don't get awarded for killing a player more than 3 times in a row!.", MSG_COLOR_MAGENTA, MSG_COLOR_WHITE);
                return false;
            }
            else if (victim->VLastGuidCount > 5 && victim->VLastGuidCount < 10)
            {
                ChatHandler(attacker).PSendSysMessage("%s[Anti Farming System]%s You have killed this guy %u times in a row now whats your problem?", MSG_COLOR_MAGENTA, MSG_COLOR_WHITE, attacker->VLastGuidCount);
                return false;
            }
            else if (victim->VLastGuidCount >= 10)
            {
                ChatHandler(attacker).PSendSysMessage("%s[Anti Farming System]%s We don't like gankers GTFO!", MSG_COLOR_MAGENTA, MSG_COLOR_WHITE);
                attacker->AddAura(15007, attacker);
                attacker->GetSession()->KickPlayer();
                return false;
            }
        }
        else
        {
            attacker->ALastGuidCount = 0;
        }
    }
    return true;
}

void GivePvPGold(Player *attacker, Player *victim)
{
    uint32 InRangeCount = 1;
    const uint32 baserewardgold = 10000;
    uint32 rewardgold = 0;
    if (sWorld.allyTowers > sWorld.hordeTowers && attacker->GetTeam() == ALLIANCE || sWorld.allyTowers < sWorld.hordeTowers && attacker->GetTeam() == HORDE)
    {
        rewardgold = rewardgold+(baserewardgold*2);
    }

    if (attacker->GetGroup())
    {
        Group* grp = attacker->GetGroup();
        Player *pGroup;
        for (GroupReference *itr = grp->GetFirstMember(); itr != NULL; itr = itr->next())
        {
            pGroup = itr->getSource();
            if (pGroup && (pGroup->GetDistance(attacker->GetPositionX(),attacker->GetPositionY(),attacker->GetPositionZ()) < 100.0f || pGroup == attacker))
            {
                InRangeCount++;
            }
        }
        rewardgold = rewardgold+((baserewardgold*2)/InRangeCount);
        for (GroupReference *itr = grp->GetFirstMember(); itr != NULL; itr = itr->next())
        {
            pGroup = itr->getSource();
            if (pGroup && (pGroup->GetDistance(attacker->GetPositionX(),attacker->GetPositionY(),attacker->GetPositionZ()) < 100.0f || pGroup == attacker))
            {
                pGroup->ModifyMoney(+rewardgold);
            }
        }
    }
    attacker->ModifyMoney(+rewardgold);
}

//This function is called when the player kills another player
void OnPVPKill(Player *attacker, Player *victim)
{
    if (DoPvPChecks(attacker,victim) == false)
        return;

    attacker->KillStreak++;
    attacker->TotalKills++;
    GivePvPGold(attacker, victim);
    attacker->ALastGuid = victim->GetGUID();
    victim->VLastGuid = attacker->GetGUID();
    return;
}

bool OnItemBuy(Creature *pCreature, Player *pPlayer, uint32 itemid)
{
	ChatHandler(pPlayer).PSendSysMessage("OnItemBuy Debug Hook Initialation");
	ChatHandler(pPlayer).PSendSysMessage("OnItemBuy Debug creatureid %s itemid %s",pCreature->GetEntry(),itemid);
    //                                                          0           1           2            3         4      5    6       7   8       9     10     11       12   13
	QueryResult_AutoPtr result = WorldDatabase.PQuery("SELECT honorrank,arenarating,arenapoints,itemlevelavg,item1,count1,item2,count2,item3,count3,rep1,repvalue1,rep2,repvalue2 FROM npc_vendor_extra WHERE creatureid = %u AND itemid = %u LIMIT 1",pCreature->GetEntry(),itemid);
    if (!result)
    {
		ChatHandler(pPlayer).PSendSysMessage("OnItemBuy Debug No Result");
        return true;
    }
    else
    {
		Oregon::Singleton<Log>::Instance().outErrorDb("Got result");
        Field *field;
        field = result->Fetch();
        uint32 honorrank        = field[0].GetUInt32();
        uint32 arenarating      = field[1].GetUInt32();
        uint32 arenapoints      = field[2].GetUInt32();
        uint32 itemlevelavg     = field[3].GetUInt32();
        uint32 item1            = field[4].GetUInt32();
        uint32 icount1          = field[5].GetUInt32();
        uint32 item2            = field[6].GetUInt32();
        uint32 icount2          = field[7].GetUInt32();
        uint32 item3            = field[8].GetUInt32();
        uint32 icount3          = field[9].GetUInt32();
        uint32 rep1             = field[10].GetUInt32();
        uint32 repvalue1        = field[11].GetUInt32();
        uint32 rep2             = field[12].GetUInt32();
        uint32 repvalue2        = field[13].GetUInt32();
		Oregon::Singleton<Log>::Instance().outErrorDb("Read all results to vars");
		ChatHandler(pPlayer).PSendSysMessage("OnItemBuy Debug Result: honorrank %s arenarating %s arenapoints %s itemlevelavg %s item1 %s icount1 %s",honorrank,arenarating,arenapoints,itemlevelavg,item1,icount1);
		ChatHandler(pPlayer).PSendSysMessage("item2 %s icount2 %s item3 %s icount3 %s rep1 %s repvalue1 %s rep2 %s repvalue2 %s",item2,icount2,item3,icount3,rep1,repvalue1,rep2,repvalue2);
		Oregon::Singleton<Log>::Instance().outErrorDb("Told the online player wtf is wrong/right");
		if (pPlayer->GetUInt32Value(PLAYER__FIELD_KNOWN_TITLES) < honorrank)
        {
            ChatHandler(pPlayer).PSendSysMessage("%s[Vendor System]%s You got honor rank: %u and you need %u!", MSG_COLOR_MAGENTA, MSG_COLOR_WHITE,pPlayer->GetUInt32Value(PLAYER__FIELD_KNOWN_TITLES), honorrank);
            return false;
        }
		Oregon::Singleton<Log>::Instance().outErrorDb("Check done: 1");
        if (!pPlayer->GetArenaPersonalRating(ARENA_TYPE_2v2) > arenarating && !pPlayer->GetArenaPersonalRating(ARENA_TYPE_3v3) > arenarating && !pPlayer->GetArenaPersonalRating(ARENA_TYPE_5v5) > arenarating)
        {
            ChatHandler(pPlayer).PSendSysMessage("%s[Vendor System]%s You need atleast %u rating in any arenateam to buy this item!", MSG_COLOR_MAGENTA, MSG_COLOR_WHITE, arenarating);
            return false;
        }
		Oregon::Singleton<Log>::Instance().outErrorDb("Check done: 2");
        if (pPlayer->GetArenaPoints() < arenapoints)
        {
            ChatHandler(pPlayer).PSendSysMessage("%s[Vendor System]%s You got %u arena points and you need %u!", MSG_COLOR_MAGENTA, MSG_COLOR_WHITE,pPlayer->GetArenaPoints(), arenapoints);
            return false;
        }
        else if (pPlayer->GetArenaPoints() >= arenapoints)
        {
            ChatHandler(pPlayer).PSendSysMessage("%s[Vendor System]%s I took %u arena points from you now!", MSG_COLOR_MAGENTA, MSG_COLOR_WHITE,arenapoints);
            pPlayer->ModifyArenaPoints(-arenapoints);
        }
		Oregon::Singleton<Log>::Instance().outErrorDb("Check done: 3");
		Oregon::Singleton<Log>::Instance().outErrorDb("Check done: 4");
        // ITEMREQ1
        if (pPlayer->HasItemCount(item1, icount1, true) == false)
        {
            QueryResult_AutoPtr result = WorldDatabase.PQuery("SELECT name FROM item_template WHERE entry = %u LIMIT 1",item1);
            if (!result)
            {
                ChatHandler(pPlayer).PSendSysMessage("%s[Vendor System]%s Item with id %u missing in the database, but is required to buy this item(%u), please report to the developers!", MSG_COLOR_MAGENTA, MSG_COLOR_WHITE,item1,itemid);
                return false;
            }
            else
            {
                field = result->Fetch();
                const char* itemname = field[0].GetString();
                ChatHandler(pPlayer).PSendSysMessage("%s[Vendor System]%s You need %u [%s] to buy this item!", MSG_COLOR_MAGENTA, MSG_COLOR_WHITE,icount1,itemname);
                return false;
            }
        } else if (pPlayer->HasItemCount(item1, icount1, true) == true)
        {
            QueryResult_AutoPtr result = WorldDatabase.PQuery("SELECT name FROM item_template WHERE entry = %u LIMIT 1",item1);
            if (!result) {return false;}
            field = result->Fetch();
            const char* itemname = field[0].GetString();
            ChatHandler(pPlayer).PSendSysMessage("%s[Vendor System]%s I took %u %s from you now!", MSG_COLOR_MAGENTA, MSG_COLOR_WHITE,icount1,itemname);
            pPlayer->DestroyItemCount(item1, -icount1, true, false);
        }
		Oregon::Singleton<Log>::Instance().outErrorDb("Check done: 5");
        // ITEMREQ2
        if (pPlayer->HasItemCount(item2, icount2, true) == false)
        {
            QueryResult_AutoPtr result = WorldDatabase.PQuery("SELECT name FROM item_template WHERE entry = %u LIMIT 1",item2);
            if (!result)
            {
                ChatHandler(pPlayer).PSendSysMessage("%s[Vendor System]%s Item with id %u missing in the database, but is required to buy this item(%u), please report to the developers!", MSG_COLOR_MAGENTA, MSG_COLOR_WHITE,item2,itemid);
                return false;
            }
            else
            {
                field = result->Fetch();
                const char* itemname = field[0].GetString();
                ChatHandler(pPlayer).PSendSysMessage("%s[Vendor System]%s You need %u [%s] to buy this item!", MSG_COLOR_MAGENTA, MSG_COLOR_WHITE,icount2,itemname);
                return false;
            }
        } else if (pPlayer->HasItemCount(item2, icount2, true) == true)
        {
            QueryResult_AutoPtr result = WorldDatabase.PQuery("SELECT name FROM item_template WHERE entry = %u LIMIT 1",item2);
            if (!result) {return false;}
            field = result->Fetch();
            const char* itemname = field[0].GetString();
            ChatHandler(pPlayer).PSendSysMessage("%s[Vendor System]%s I took %u %s from you now!", MSG_COLOR_MAGENTA, MSG_COLOR_WHITE,icount2,itemname);
            pPlayer->DestroyItemCount(item2, -icount2, true, false);
        }
		Oregon::Singleton<Log>::Instance().outErrorDb("Check done: 6");
        // ITEMREQ3
        if (pPlayer->HasItemCount(item3, icount3, true) == false)
        {
            QueryResult_AutoPtr result = WorldDatabase.PQuery("SELECT name FROM item_template WHERE entry = %u LIMIT 1",item3);
            if (!result)
            {
                ChatHandler(pPlayer).PSendSysMessage("%s[Vendor System]%s Item with id %u missing in the database, but is required to buy this item(%u), please report to the developers!", MSG_COLOR_MAGENTA, MSG_COLOR_WHITE,item3,itemid);
                return false;
            }
            else
            {
                field = result->Fetch();
                const char* itemname = field[0].GetString();
                ChatHandler(pPlayer).PSendSysMessage("%s[Vendor System]%s You need %u [%s] to buy this item!", MSG_COLOR_MAGENTA, MSG_COLOR_WHITE,icount3,itemname);
                return false;
            }
        } else if (pPlayer->HasItemCount(item3, icount3, true) == true)
        {
            QueryResult_AutoPtr result = WorldDatabase.PQuery("SELECT name FROM item_template WHERE entry = %u LIMIT 1",item3);
            if (!result) {return false;}
            field = result->Fetch();
            const char* itemname = field[0].GetString();
            ChatHandler(pPlayer).PSendSysMessage("%s[Vendor System]%s I took %u %s from you now!", MSG_COLOR_MAGENTA, MSG_COLOR_WHITE,icount3,itemname);
            pPlayer->DestroyItemCount(item3, -icount3, true, false);
        }
		Oregon::Singleton<Log>::Instance().outErrorDb("Check done: 7");
        // REPREQ1
        if (pPlayer->GetReputation(rep1) < repvalue1)
        {
            ChatHandler(pPlayer).PSendSysMessage("%s[Vendor System]%s You need %u reputation with %u to buy this item!", MSG_COLOR_MAGENTA, MSG_COLOR_WHITE,repvalue1, rep1);
            return false;
        }Oregon::Singleton<Log>::Instance().outErrorDb("Check done: 8");
        // REPREQ2
        if (pPlayer->GetReputation(rep2) < repvalue2)
        {
            ChatHandler(pPlayer).PSendSysMessage("%s[Vendor System]%s You need %u reputation with %u to buy this item!", MSG_COLOR_MAGENTA, MSG_COLOR_WHITE,repvalue2, rep2);
            return false;
        }Oregon::Singleton<Log>::Instance().outErrorDb("Check done: 9");
        uint32 tempcount = 0;
        uint32 tempilevelcount = 0;
        uint32 ilvlavg = 0;
        for (uint8 i = EQUIPMENT_SLOT_START; i < EQUIPMENT_SLOT_END; i++)
        {
            Item *pItem = pPlayer->GetItemByPos(i);
            if (pItem)
            {
                tempcount++;
                tempilevelcount += pItem->GetProto()->ItemLevel;
            }
            else if (i != EQUIPMENT_SLOT_OFFHAND && i != EQUIPMENT_SLOT_TABARD && i != EQUIPMENT_SLOT_BODY)
            {
                tempcount++;
            }
        }
        ilvlavg = tempilevelcount/tempcount;
        if (ilvlavg <= itemlevelavg)
        {
            ChatHandler(pPlayer).PSendSysMessage("%s[Vendor System]%s You need a averange item level of %u to buy this item, currently you have %u", MSG_COLOR_MAGENTA, MSG_COLOR_WHITE,itemlevelavg, ilvlavg);
            return false;
        }Oregon::Singleton<Log>::Instance().outErrorDb("Check done: 10");
    }
}

void AddSC_onevents()
{
    Script *newscript;
    newscript = new Script;
    newscript->Name = "scripted_on_events";
    newscript->pOnLogin = &OnLogin;
    newscript->pOnPVPKill = &OnPVPKill;
    newscript->pOnItemBuy = &OnItemBuy;
    newscript->RegisterSelf();
}
